import math
import sys
import re

class ScientificCalculator:
    def __init__(self):
        self.angle_mode = 'deg'  # 默认角度模式为角度（已修改）
        self.history = []        # 计算历史记录
        self.memory = 0          # 存储记忆值
        self.precision = 10      # 默认显示精度
    
    def set_angle_mode(self, mode):
        """设置角度模式（弧度或角度）"""
        if mode in ['rad', 'deg']:
            self.angle_mode = mode
            return f"角度模式已设置为 {'度' if mode == 'deg' else '弧度'}"
        return "无效的角度模式，请使用 'rad' 或 'deg'"
    
    def set_precision(self, precision):
        """设置结果显示精度"""
        try:
            self.precision = max(0, min(int(precision), 15))
            return f"显示精度已设置为 {self.precision} 位小数"
        except ValueError:
            return "无效的精度设置，请输入 0-15 之间的整数"
    
    def calculate(self, expression):
        """计算表达式并返回结果"""
        try:
            # 保存原始表达式用于历史记录
            original_expression = expression
            
            # 预处理表达式
            expression = expression.replace(' ', '')  # 移除空格
            expression = expression.replace('^', '**')  # 将^替换为**
            expression = expression.replace('pi', str(math.pi))  # 替换pi
            expression = expression.replace('e', str(math.e))  # 替换e
            
            # 处理阶乘（n!）
            expression = self.process_factorial(expression)
            
            # 处理函数调用
            expression = self.process_functions(expression)
            
            # 评估表达式
            result = eval(expression)
            
            # 保存到历史记录
            self.history.append(f"{original_expression} = {self.format_result(result)}")
            if len(self.history) > 10:
                self.history.pop(0)
                
            return result
        except Exception as e:
            return f"计算错误: {str(e)}"
    
    def format_result(self, result):
        """格式化结果，处理浮点数精度问题"""
        if isinstance(result, float):
            # 四舍五入到指定精度
            rounded = round(result, self.precision)
            
            # 检查是否可以表示为整数
            if abs(rounded - round(rounded)) < 1e-10:
                return int(round(rounded))
            
            # 处理常见的精确值
            exact_values = {
                0.5: "0.5",
                0.25: "0.25",
                0.75: "0.75",
                0.3333333333333333: "1/3",
                0.6666666666666666: "2/3",
                0.125: "0.125",
                0.375: "0.375",
                0.625: "0.625",
                0.875: "0.875"
            }
            
            # 检查是否匹配精确值
            for value, representation in exact_values.items():
                if abs(result - value) < 1e-10:
                    return representation
            
            # 检查是否接近常见分数
            for denom in range(2, 10):
                for numer in range(1, denom):
                    fraction = numer / denom
                    if abs(result - fraction) < 1e-10:
                        return f"{numer}/{denom}"
            
            # 返回四舍五入后的值
            return rounded
        
        return result
    
    def process_factorial(self, expression):
        """处理阶乘运算"""
        # 使用正则表达式匹配数字阶乘（如5!）
        pattern = r'(\d+)!'
        while True:
            match = re.search(pattern, expression)
            if not match:
                break
            num = int(match.group(1))
            fact = str(math.factorial(num))
            expression = expression.replace(match.group(0), fact, 1)
        return expression
    
    def process_functions(self, expression):
        """处理函数调用，考虑角度模式"""
        # 函数映射
        func_map = {
            'sin': math.sin,
            'cos': math.cos,
            'tan': math.tan,
            'asin': math.asin,
            'acos': math.acos,
            'atan': math.atan,
            'sqrt': math.sqrt,
            'log10': math.log10,
            'log': math.log,
            'exp': math.exp,
            'factorial': math.factorial,
            'fact': math.factorial,
            'pow': math.pow,
            'abs': abs
        }
        
        # 修正：允许函数名包含数字（如log10）
        pattern = r'([a-zA-Z_]\w*)\(([^\(\)]+)\)'
        while True:
            match = re.search(pattern, expression)
            if not match:
                break
            
            func_name = match.group(1)
            arg_str = match.group(2)
            
            if func_name not in func_map:
                # 如果不是已知函数，保留原样
                break
                
            # 计算参数值
            arg_value = eval(arg_str)
            
            # 处理三角函数的角度转换
            if self.angle_mode == 'deg':
                if func_name in ['sin', 'cos', 'tan']:
                    # 转换为弧度
                    arg_rad = math.radians(arg_value)
                    # 计算三角函数
                    result = func_map[func_name](arg_rad)
                    # 处理常见角度
                    if arg_value in [0, 30, 45, 60, 90, 180, 270, 360]:
                        common_values = {
                            0: 0, 
                            30: 0.5, 
                            45: math.sqrt(2)/2, 
                            60: math.sqrt(3)/2, 
                            90: 1, 
                            180: 0, 
                            270: -1, 
                            360: 0
                        }
                        result = common_values[arg_value]
                    expression = expression.replace(match.group(0), str(result), 1)
                    continue
                elif func_name in ['asin', 'acos', 'atan']:
                    result = func_map[func_name](arg_value)
                    result_deg = math.degrees(result)
                    expression = expression.replace(match.group(0), str(result_deg), 1)
                    continue
            
            # 计算函数结果
            # 修复：使用正确的函数计算
            if func_name == 'log10':
                result = math.log10(arg_value)
            elif func_name == 'log':
                result = math.log(arg_value)
            else:
                result = func_map[func_name](arg_value)
                
            expression = expression.replace(match.group(0), str(result), 1)
        
        return expression
    
    def memory_store(self, value):
        """存储值到记忆"""
        self.memory = value
        return f"已存储: {value}"
    
    def memory_recall(self):
        """从记忆召回值"""
        return self.memory
    
    def memory_add(self, value):
        """将值加到记忆"""
        self.memory += value
        return f"记忆值更新为: {self.memory}"
    
    def memory_subtract(self, value):
        """从记忆减去值"""
        self.memory -= value
        return f"记忆值更新为: {self.memory}"
    
    def memory_clear(self):
        """清除记忆"""
        self.memory = 0
        return "记忆已清除"
    
    def show_history(self):
        """显示计算历史"""
        if not self.history:
            return "历史记录为空"
        return "\n".join(self.history)
    
    def clear_history(self):
        """清除计算历史"""
        self.history = []
        return "历史记录已清除"
    
    def help(self):
        """显示帮助信息"""
        help_text = f"""
        === 科学计算器帮助 ===
        支持的运算:
          基本运算: +, -, *, /, ^ (幂运算)
          三角函数: sin(), cos(), tan(), asin(), acos(), atan()
          对数指数: log() [自然对数], log10() [常用对数], exp()
          其他函数: sqrt() [平方根], abs() [绝对值], factorial() 或 fact() [阶乘]
          常量: pi, e
        
        角度模式:
          deg - 角度制 (默认)
          rad - 弧度制
        
        精度设置: 
          当前显示精度: {self.precision} 位小数
          使用 precision [数字] 设置精度 (0-15)
        
        记忆功能:
          MS - 存储值到记忆
          MR - 召回记忆值
          M+ - 将值加到记忆
          M- - 从记忆减去值
          MC - 清除记忆
        
        其他命令:
          history - 显示计算历史
          clear - 清除历史记录
          mode - 切换角度模式 (deg/rad)
          precision - 设置显示精度
          help - 显示帮助
          exit - 退出计算器
        
        注意: 
          1. 函数参数请用括号括起来，如 sin(30)
          2. 角度模式下三角函数参数应为度数
          3. 反三角函数在角度模式下返回度数
          4. 常见角度值会返回精确结果
        """
        return help_text

def main():
    calc = ScientificCalculator()
    print("=== 科学计算器 ===")
    print("输入 'help' 查看帮助, 'exit' 退出程序")
    
    while True:
        try:
            user_input = input("\n> ").strip()
            
            if not user_input:
                continue
            
            if user_input.lower() == 'exit':
                print("感谢使用科学计算器，再见！")
                sys.exit(0)
            
            if user_input.lower() == 'help':
                print(calc.help())
                continue
                
            if user_input.lower() == 'history':
                print(calc.show_history())
                continue
                
            if user_input.lower() == 'clear':
                print(calc.clear_history())
                continue
                
            if user_input.lower().startswith('mode '):
                mode = user_input.split()[1].lower()
                print(calc.set_angle_mode(mode))
                continue
                
            if user_input.lower().startswith('precision '):
                try:
                    precision = int(user_input.split()[1])
                    print(calc.set_precision(precision))
                except (IndexError, ValueError):
                    print("无效的精度设置，请输入 'precision [数字]' (0-15)")
                continue
                
            # 记忆功能处理
            if user_input.upper() == 'MS':
                if calc.history:
                    last_result = float(calc.history[-1].split('=')[1].strip())
                    print(calc.memory_store(last_result))
                else:
                    print("历史记录为空，无法存储")
                continue
                    
            if user_input.upper() == 'MR':
                print(calc.memory_recall())
                continue
                
            if user_input.upper() == 'MC':
                print(calc.memory_clear())
                continue
                
            if user_input.upper() == 'M+':
                if calc.history:
                    last_result = float(calc.history[-1].split('=')[1].strip())
                    print(calc.memory_add(last_result))
                else:
                    print("历史记录为空，无法添加")
                continue
                    
            if user_input.upper() == 'M-':
                if calc.history:
                    last_result = float(calc.history[-1].split('=')[1].strip())
                    print(calc.memory_subtract(last_result))
                else:
                    print("历史记录为空，无法减去")
                continue
            
            # 计算表达式
            result = calc.calculate(user_input)
            formatted_result = calc.format_result(result)
            print(f"结果: {formatted_result}")
            
        except KeyboardInterrupt:
            print("\n感谢使用科学计算器，再见！")
            sys.exit(0)
        except Exception as e:
            print(f"错误: {str(e)}")

if __name__ == "__main__":
    main()